package cn.bugstack.service.impl;

import cn.bugstack.common.constants.Constants;
import cn.bugstack.dao.IOrderDao;
import cn.bugstack.domain.po.PayOrder;
import cn.bugstack.domain.req.ShopCartReq;
import cn.bugstack.domain.res.PayOrderRes;
import cn.bugstack.domain.vo.ProductVO;
import cn.bugstack.service.IOrderService;
import cn.bugstack.service.rpc.ProductRPC;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.google.common.eventbus.EventBus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class OrderServiceImpl implements IOrderService {

    @Value("${alipay.notify-url}")
    private String notifyUrl;
    @Value("${alipay.return_url}")
    private String returnUrl;


    @Resource
    private IOrderDao orderDao;

    @Resource
    private ProductRPC productRPC;

    @Resource
    private AlipayClient alipayClient;

    @Resource
    private EventBus eventBus;

    /**
     * 创建订单
     *
     * @param shopCartReq 购物车请求对象
     *                    包含用户ID和商品ID
     * @return 订单响应对象
     */
    @Override
    public PayOrderRes createOrder(ShopCartReq shopCartReq) throws Exception {
        // 1. 查询当前用户是否有未支付订单或者掉单订单
        PayOrder payOrderReq = new PayOrder();
        payOrderReq.setUserId(shopCartReq.getUserId());
        payOrderReq.setOrderId(shopCartReq.getProductId());

        // 2. 如果有未支付订单（同用户同商品的未支付订单），直接返回该订单信息
        PayOrder unpaidOrder = orderDao.queryUnPayOrder(payOrderReq);

        if(unpaidOrder != null && unpaidOrder.getStatus().equals(Constants.OrderStatusEnum.PAY_WAIT.getCode())) {
            log.info("用户 {} 有未支付订单，订单ID: {}", shopCartReq.getUserId(), unpaidOrder.getOrderId());
            return PayOrderRes.builder()
                    .orderId(unpaidOrder.getOrderId())
                    .payUrl(unpaidOrder.getPayUrl())
                    .build();
        }else if(unpaidOrder != null && unpaidOrder.getStatus().equals(Constants.OrderStatusEnum.CREATE.getCode())) {
            log.info("用户 {} 有掉单订单，订单ID: {}", shopCartReq.getUserId(), unpaidOrder.getOrderId());
            // 如果是掉单订单，重新创建支付单(即本地订单创建成功，但是支付宝订单创建失败)
            // todo 调用支付宝创建订单
            PayOrder payOrder = this.doPrepayOrder(shopCartReq.getUserId(),
                    shopCartReq.getProductId(),
                    unpaidOrder.getProductName(),
                    unpaidOrder.getOrderId(),
                    unpaidOrder.getTotalAmount());
            return PayOrderRes.builder()
                    .orderId(payOrder.getOrderId())
                    .payUrl(payOrder.getPayUrl())
                    .build();

        }

        // 2. 查询订单 & 创建订单
        ProductVO productVO = productRPC.queryProductById(shopCartReq.getProductId());
        String orderId = RandomStringUtils.randomNumeric(16);
        PayOrder newOrder = PayOrder.builder()
                .orderId(orderId)
                .userId(shopCartReq.getUserId())
                .productId(shopCartReq.getProductId())
                .productName(productVO.getProductName())
                .totalAmount(productVO.getPrice())
                .status(Constants.OrderStatusEnum.CREATE.getCode())
                .orderTime(new Date(System.currentTimeMillis()))
                .build();
        orderDao.insert(newOrder);

        // 3. 创建支付单
        // todo 调用支付宝创建订单
        PayOrder payOrder = doPrepayOrder(shopCartReq.getUserId(), shopCartReq.getProductId(), productVO.getProductName(), orderId, productVO.getPrice());
        log.info("用户 {} 创建订单成功，订单ID: {}", shopCartReq.getUserId(), orderId);

        return PayOrderRes.builder()
                .userId(shopCartReq.getUserId())
                .orderId(orderId)
                .payUrl(payOrder.getPayUrl()) // 模拟支付链接
                .build();
    }

    @Override
    public void changeOrderPaySuccess(String orderId) {
        PayOrder payOrderReq = new PayOrder();
        payOrderReq.setOrderId(orderId);
        payOrderReq.setStatus(Constants.OrderStatusEnum.PAY_SUCCESS.getCode());
        orderDao.changeOrderPaySuccess(payOrderReq);

        // 发布支付成功事件
        eventBus.post(JSON.toJSONString(payOrderReq));
    }

    /*
     * 等待支付状态超过1分钟的订单视为回调失败的订单
     */
    @Override
    public List<String> queryNoPayNotifyOrder() {
        return orderDao.queryNoPayNotifyOrder();
    }

    @Override
    public List<String> queryTimeoutCloseOrderList() {
        return orderDao.queryTimeoutCloseOrderList();
    }

    @Override
    public boolean changeOrderClose(String orderId) {
        return orderDao.changeOrderClose(orderId);
    }

    private PayOrder doPrepayOrder(String userId, String productId, String productName, String orderId, BigDecimal totalAmount) throws AlipayApiException {
        // Page: 网页支付
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(notifyUrl);
        request.setReturnUrl(returnUrl);

        Map<String,String> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", orderId);
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        bizContent.put("total_amount", totalAmount.toString());
        bizContent.put("subject", productName);
        request.setBizContent(JSON.toJSONString(bizContent));
        // Biz: business缩写，指业务数据

        String form = alipayClient.pageExecute(request).getBody();

        PayOrder payOrder = new PayOrder();
        payOrder.setOrderId(orderId);
        payOrder.setPayUrl(form);
        payOrder.setStatus(Constants.OrderStatusEnum.PAY_WAIT.getCode()); // 设置为等待支付状态

        orderDao.updateOrderPayInfo(payOrder);

        return payOrder;
    }
}
